package org.brakepedal.server.config;

import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.connector.Connector;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.web.servlet.TomcatServletWebServerFactoryCustomizer;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.*;
import org.springframework.web.util.UrlPathHelper;

import java.util.ArrayList;
import java.util.List;

/**
 * Date: 2023/2/4 19:51
*/
@Slf4j
@Getter
@Configuration
@RequiredArgsConstructor
//@EnableWebMvc // 这个会取代 MVC 的AutoConfiguration所配置的MVC配置, 会覆盖掉一些默认配置, 比如静态资源映射就会被覆盖,导致访问静态资源404
public class CustomWebMvcConfig implements WebMvcConfigurer {

    private  List<HandlerInterceptor> interceptorList;

    private  List<HandlerMethodArgumentResolver> argumentResolverList;

    private final MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter;
    private final StringHttpMessageConverter stringHttpMessageConverter;

    @Override
    public void addInterceptors(@NotNull InterceptorRegistry registry) {
        if (interceptorList == null) {
            return;
        }
        for (HandlerInterceptor interceptor: interceptorList) {
            registry.addInterceptor(interceptor);
        }
    }

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOriginPatterns("*")
                .allowedHeaders("*")
                .allowedMethods("*")
                .exposedHeaders("*")
                ;
    }

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        UrlPathHelper urlPathHelper = new UrlPathHelper();
        urlPathHelper.setUrlDecode(false);
        urlPathHelper.setAlwaysUseFullPath(true);//设置总使用完整路径
        configurer.setUseSuffixPatternMatch(false)
                  .setUseRegisteredSuffixPatternMatch(true)
                  .setUseTrailingSlashMatch(true) // 自动后缀路径模式匹配
                  .setUrlPathHelper(urlPathHelper);
    }

    @Override
    public void addArgumentResolvers(@NotNull List<HandlerMethodArgumentResolver> resolvers){
        /*if(argumentResolvers != null) {
            for (HandlerMethodArgumentResolver re : argumentResolvers) {
                log.info("argumentResolver: {}",re);
                resolvers.add(re);
            }
        }
        resolvers.forEach(res->log.info("resolver list:{}",res));*/
//        resolvers.add(thisUserResolver);
    }


    @Autowired(required = false)
    public void setInterceptorList(List<HandlerInterceptor> interceptorList) {
        this.interceptorList = interceptorList;
    }

    @Autowired(required = false)
    public void setArgumentResolverList(List<HandlerMethodArgumentResolver> argumentResolverList) {
        this.argumentResolverList = argumentResolverList;
    }

    @Override
    public void addResourceHandlers(
            @NotNull ResourceHandlerRegistry registry
    ) {
        // 如果没有/webjars/**的映射, 那就加回来
        if (!registry.hasMappingForPattern("/webjars/**")) {
            registry.addResourceHandler("/webjars/**").addResourceLocations(
                    "classpath:/META-INF/resources/webjars/");
        }
        if(!registry.hasMappingForPattern("/**")) {
            registry.addResourceHandler("/**")
                    .addResourceLocations("classpath:/static");
        }
    }

    public static @NotNull String normalizeUploadFileUrlPrefix(@NotNull String uploadFileUrlPrefix) {
        StringBuilder builder = new StringBuilder(uploadFileUrlPrefix);
        if(builder.charAt(0)=='/') {
            builder.deleteCharAt(0);
        }
        if(builder.charAt(builder.length()-1)=='/') {
            builder.deleteCharAt(builder.length()-1);
        }
        return builder.toString();
    }

//    @Bean
//    public WebServerFactoryCustomizer<ConfigurableWebServerFactory> webServerFactoryCustomizer() {
//        //第二种写法：java8 lambda写法
//        return factory -> {
//            ErrorPage errorPage404 = new ErrorPage(HttpStatus.NOT_FOUND, "/_index.html");
//            factory.addErrorPages(errorPage404);
//        };
//    }

    /**
     * 提前将 {@code MappingJackson2HttpMessageConverter} 置于 响应体信息转换器列表前, 是为了
     * 让 {@code MappingJackson2HttpMessageConverter} 先一步 {@code StringHttpMessageConverter} 转换 Controller
     * (已经让Advisers处理过方法返回值了) 的返回值, 否则, 会把 自定义的一些返回格式 被简直 转为 String
     * 抛出 {@code ClassCaseException} bug 记录在 下面的链接里
     * @see  <a href="https://www.cnblogs.com/oldboyooxx/p/10824531.html">bug记录</a>
     * */
    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        List<HttpMessageConverter<?>> httpMessageConverters = new ArrayList<>(converters.stream().filter(converter -> !(converter instanceof MappingJackson2HttpMessageConverter) && !(converter instanceof StringHttpMessageConverter)).toList());
        httpMessageConverters.add(mappingJackson2HttpMessageConverter);
        httpMessageConverters.add(stringHttpMessageConverter);
        converters.clear();
        converters.addAll(httpMessageConverters);
//        log.trace("handled converters: {}",converters);
    }

    /*  @Bean
    public CorsFilter corsFilter(){
        CorsConfiguration config = new CorsConfiguration();
        config.addAllowedOriginPattern("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        UrlBasedCorsConfigurationSource configurationSource = new UrlBasedCorsConfigurationSource();
        configurationSource.registerCorsConfiguration("/**",config);
        return new CorsFilter(configurationSource);
    }*/

    /*@Bean
    public FilterRegistrationBean<CorsFilter> filterRegistrationBean(CorsFilter filter) {
        FilterRegistrationBean<CorsFilter> filterRegistrationBean = new FilterRegistrationBean<>();
        filterRegistrationBean.setFilter(filter);	// 这里可以使用 new，也可以在 Filter 上加 @Component 注入进来
        filterRegistrationBean.addUrlPatterns("/**");
//        filterRegistrationBean.setName("NotFoundResetFilter");
        filterRegistrationBean.setOrder(1);	// 值越小，优先级越高
        return filterRegistrationBean;
    }*/
}
